"""Fortran analyzer adapter for the unified interface."""

from __future__ import annotations

import sys
from pathlib import Path
from typing import List, Dict, Any
import re

# Add FortranFlowMap to path
sys.path.insert(0, str(Path(__file__).parent.parent.parent / "FortranFlowMap"))

try:
    from Tools.process_files import process_file
    from Tools.build_tree import build_tree
    from Tools.analyze_tree import analyze_subroutine_to_string
    from Tools.print_tree import generate_relationships, locate_subroutines_in_files
    FORTRAN_ANALYZER_AVAILABLE = True
except ImportError:
    FORTRAN_ANALYZER_AVAILABLE = False

from .base import LanguageAnalyzer, AnalysisResult, FunctionInfo, CallGraph


class FortranAnalyzerAdapter(LanguageAnalyzer):
    """Adapter for the Fortran analyzer."""

    def analyze(self, paths: List[Path], **kwargs) -> AnalysisResult:
        """Analyze Fortran files using the FortranFlowMap analyzer."""
        if not FORTRAN_ANALYZER_AVAILABLE:
            raise RuntimeError("Fortran analyzer not available")

        # Process all Fortran files to build relationships
        relationships = {}
        all_functions = []

        for path in paths:
            if path.is_file() and path.suffix.lower() in self.get_supported_extensions():
                # Process individual file
                try:
                    file_relationships, file_functions = self._process_fortran_file(path)
                    relationships.update(file_relationships)
                    all_functions.extend(file_functions)
                except Exception as e:
                    print(f"Warning: Error processing {path}: {e}")
            elif path.is_dir():
                # Process directory recursively
                for fortran_file in path.rglob("*"):
                    if fortran_file.is_file() and fortran_file.suffix.lower() in self.get_supported_extensions():
                        try:
                            file_relationships, file_functions = self._process_fortran_file(fortran_file)
                            relationships.update(file_relationships)
                            all_functions.extend(file_functions)
                        except Exception as e:
                            print(f"Warning: Error processing {fortran_file}: {e}")

        # Build call graph from relationships
        call_graph = self._build_call_graph(relationships)

        # Generate statistics
        statistics = self._generate_statistics(all_functions, call_graph)

        return AnalysisResult(
            functions=all_functions,
            call_graph=call_graph,
            cycles=[],  # TODO: Implement cycle detection
            statistics=statistics,
            language="fortran"
        )

    def _process_fortran_file(self, file_path: Path) -> tuple[Dict[str, Any], List[FunctionInfo]]:
        """Process a single Fortran file."""
        relationships = {}
        functions = []

        try:
            # Use FortranFlowMap to process the file
            content = file_path.read_text()
            file_relationships = process_file(str(file_path))

            if file_relationships:
                relationships.update(file_relationships)

            # Extract function information from the file
            extracted_functions = self._extract_functions_from_content(content, str(file_path))
            functions.extend(extracted_functions)

        except Exception as e:
            print(f"Error processing Fortran file {file_path}: {e}")

        return relationships, functions

    def _extract_functions_from_content(self, content: str, file_path: str) -> List[FunctionInfo]:
        """Extract function information from Fortran source."""
        functions = []
        lines = content.splitlines()

        # Patterns for Fortran subroutines and functions
        subroutine_pattern = re.compile(
            r'^\s*(subroutine|function)\s+([a-zA-Z_][a-zA-Z0-9_]*)',
            re.IGNORECASE
        )
        end_pattern = re.compile(
            r'^\s*end\s+(subroutine|function)(?:\s+([a-zA-Z_][a-zA-Z0-9_]*))?',
            re.IGNORECASE
        )

        current_function = None
        for line_no, line in enumerate(lines, 1):
            subroutine_match = subroutine_pattern.match(line)
            if subroutine_match:
                func_type = subroutine_match.group(1).lower()
                func_name = subroutine_match.group(2)

                current_function = FunctionInfo(
                    name=func_name,
                    full_name=func_name,
                    return_type=func_type,
                    source_file=file_path,
                    start_line=line_no,
                    language="fortran"
                )
                continue

            end_match = end_pattern.match(line)
            if end_match and current_function:
                current_function.end_line = line_no
                current_function.line_count = line_no - current_function.start_line + 1
                functions.append(current_function)
                current_function = None

        # Handle functions that don't have explicit end statements
        if current_function:
            current_function.end_line = len(lines)
            current_function.line_count = current_function.end_line - current_function.start_line + 1
            functions.append(current_function)

        return functions

    def _build_call_graph(self, relationships: Dict[str, Any]) -> CallGraph:
        """Build call graph from FortranFlowMap relationships."""
        call_graph = CallGraph()

        for caller, callees in relationships.items():
            if isinstance(callees, list):
                for callee in callees:
                    if isinstance(callee, str):
                        call_graph.add_call(caller, callee)
            elif isinstance(callees, dict):
                # Handle more complex relationship structures
                for callee in callees.keys():
                    call_graph.add_call(caller, callee)

        return call_graph

    def _generate_statistics(self, functions: List[FunctionInfo], call_graph: CallGraph) -> Dict[str, Any]:
        """Generate analysis statistics."""
        stats = {
            'total_functions': len(functions),
            'total_calls': sum(len(callees) for callees in call_graph.edges.values()),
            'average_function_length': 0,
            'largest_function': None,
            'source_files': set()
        }

        if functions:
            line_counts = [f.line_count for f in functions if f.line_count > 0]
            if line_counts:
                stats['average_function_length'] = sum(line_counts) / len(line_counts)
                largest_func = max(functions, key=lambda f: f.line_count)
                stats['largest_function'] = {
                    'name': largest_func.full_name,
                    'line_count': largest_func.line_count
                }

            # Collect source files
            for func in functions:
                if func.source_file:
                    stats['source_files'].add(func.source_file)

            stats['source_files'] = len(stats['source_files'])

        return stats

    def get_supported_extensions(self) -> List[str]:
        """Return supported Fortran file extensions."""
        return ['.f', '.f90', '.f95', '.f03', '.f08', '.for', '.ftn']

    def get_language_name(self) -> str:
        """Return the language name."""
        return "fortran"